package com.tbit.uqbike.client.service.impl;

import com.tbit.uqbike.client.constant.MapConstant;
import com.tbit.uqbike.client.constant.SysConstant;
import com.tbit.uqbike.client.dao.core.GeoDao;
import com.tbit.uqbike.client.dao.core.RideLogDao;
import com.tbit.uqbike.client.pojo.*;
import com.tbit.uqbike.client.service.*;
import com.tbit.uqbike.client.util.GeoUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

/**
 * 电子围栏
 *
 * @author Leon
 * 2019年10月16日 下午8:08:40
 */
@Service("geoService")
public class GeoServiceImpl implements GeoService {
    @Autowired
    private MachineBorrowService machineBorrowService;
    @Autowired
    private GeoDao geoDao;
    @Autowired
    private MachineService machineService;
    @Autowired
    private CalibrateService calibrateService;
    @Autowired
    private CacheService cacheService;
    @Autowired
    private RideLogDao rideLogDao;

    @Override
    public List<Geo> findNearGeo(User user, Point point, Integer getMapType, Integer radius, Integer accountId) {
        List<Geo> geos = new ArrayList<Geo>();
        if (radius == null) {
            radius = 1000;
        }
        if (user == null) {
            List<Geo> geoDBs;
            if (accountId != null) {
                geoDBs = geoDao.getByBrandId(accountId);
            } else {
                geoDBs = geoDao.getAll();
            }
            /**查询所有电子围栏*/
            for (Geo g : geoDBs) {
                if (GeoUtil.IsPtInPoly(point, GeoUtil.getPoints(g.getPoints()))) {
                    geos.add(g);
                }
            }
        } else {
            //查询用户是否借车
            MachineBorrow machineBorrow = machineBorrowService.getByUserId(user.getUserId());
            if (machineBorrow == null) {
                /**查询附近的所有电子围栏 */
    			/*Double area=0.00001D*radius;
    			Map<String,Object> params=new HashMap<String,Object>();
    			params.put("minLo", point.getX()-area);
    			params.put("maxLo", point.getX()+area);
    			params.put("minLa", point.getY()-area);
    			params.put("maxLa", point.getY()+area);*/
                /**查询品牌下所有电子围栏*/
                List<Geo> geoDBs = geoDao.getByBrandId(user.getAccountId());
                for (Geo g : geoDBs) {
                    if (GeoUtil.IsPtInPoly(point, GeoUtil.getPoints(g.getPoints()))) {
                        geos.add(g);
                    }
                }
            } else {
                Machine machine = machineService.getByMachineId(machineBorrow.getMachineId());
                /**查询附近的所有电子围栏 */
                List<Geo> geoDBs = geoDao.getByBrandId(user.getAccountId());
                for (Geo g : geoDBs) {
                    if (GeoUtil.IsPtInPoly(point, GeoUtil.getPoints(g.getPoints())) && g.getAccountId().equals(machine.getAccountId())) {
                        geos.add(g);
                    }
                }
            }
        }
        /**经纬度校验 */
        for (Geo geo : geos) {
            calibrateService.calGeo(geo, MapConstant.MAP_ORI, getMapType);
        }
        return geos;
    }

    @Override
    public List<Geo> getByAccountId(Integer accountId) {
        return cacheService.getGeo(accountId);
    }

    @Override
    public Boolean checkInGeo(Integer accountId, Point point) {
        /**判断代理商是否设置运营区域*/
        List<Geo> geos = getByAccountId(accountId);
        if (geos.size() > 0) {
            Geo geo = geos.get(0);
            if (geo.getGeoSwitch() != null && geo.getGeoSwitch() == 1) {
                List<Point> points = geo.getPointList();
                /**判断是否在运营区域内*/
                if (geo.getPointList() == null) {
                    points = GeoUtil.getPoints(geo.getPoints());
                }
                Boolean isInArea = GeoUtil.IsPtInPoly(point, points);

                if (!isInArea) {
                    return false;
                }
            }
        } else {
            return false;
        }
        return true;
    }

    @Override
    public List<Geo> getByBrandId(Integer accountId) {
        return geoDao.getByBrandId(accountId);
    }

    @Override
    public Geo getByBrandId(Integer accountId, Point point) {
        /**根据品牌查询所有电子围栏*/
        List<Geo> geos = getByBrandId(accountId);
        for (Geo geo : geos) {
            /**判断是否在运营区域内*/
            List<Point> points = GeoUtil.getPoints(geo.getPoints());
            Boolean isInArea = GeoUtil.IsPtInPoly(point, points);
            if (isInArea) {
                return geo;
                /**点到电子围栏距离小于等于500米认为也在围栏内*/
            } else if (GeoUtil.getDistance(point, points) <= 500) {
                return geo;
            }
        }
        return null;
    }

    @Override
    public Geo getByBrandIdAndUserId(Integer accountId, Point point, Integer userId) {
        /**根据品牌查询所有电子围栏*/
        List<Geo> geos = getByBrandId(accountId);
        List<Geo> actualGeos = new ArrayList<>();
        for (Geo geo : geos) {
            /**判断是否在运营区域内*/
            List<Point> points = GeoUtil.getPoints(geo.getPoints());
            Boolean isInArea = GeoUtil.IsPtInPoly(point, points);
            if (isInArea) {
                actualGeos.add(geo);
                /**点到电子围栏距离小于等于500米认为也在围栏内*/
            } else if (GeoUtil.getDistance(point, points) <= 500) {
                actualGeos.add(geo);
            }
        }
        if (actualGeos.size() == 1) {
            //没区域重叠的情况
            return actualGeos.get(0);
        }
        if (actualGeos.size() > 1) {
            //区域重叠，查询用户上次骑行区域
            RideLog rideLog = rideLogDao.findLastByUserId(userId);
            if (rideLog != null) {
                for (Geo actualGeo : actualGeos) {
                    if (rideLog.getAccountId().equals(actualGeo.getAccountId())) {
                        return actualGeo;
                    }
                }
            }
            //未匹配到骑行订单，直接返回第一个区域
            return actualGeos.get(0);
        }
        return null;
    }

    @Override
    public Integer getBelongAccountAndUserId(Integer accountId, Double lo, Double la, Integer mapType, Integer userId) {
        Integer agentId = null;
        if (mapType == null) {
            mapType = MapConstant.MAP_GOOGLE;
        }

        /* 校准百度经纬度为原始经纬度 */
        Point point = new Point(lo, la);
        point = calibrateService.calibrate(point, mapType, SysConstant.ORIGINAL);
        Geo geo = getByBrandIdAndUserId(accountId, point, userId);

        if (geo != null) {
            agentId = geo.getAccountId();
        }
        return agentId;
    }

    @Override
    public Integer getBelongAccount(Integer accountId, Double lo, Double la, Integer mapType) {
        Integer agentId = null;

        if (mapType == null) {
            mapType = MapConstant.MAP_GOOGLE;
        }

        /* 校准百度经纬度为原始经纬度 */
        Point point = new Point(lo, la);
        point = calibrateService.calibrate(point, mapType, SysConstant.ORIGINAL);

        Geo geo = getByBrandId(accountId, point);

        if (geo != null) {
            agentId = geo.getAccountId();
        }

        return agentId;
    }
}
